package com.hys.authserver.auth;

import com.hys.authserver.utils.RedisUtils;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.authentication.password.CompromisedPasswordChecker;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsPasswordService;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.Assert;

/**
 * IDE: IntelliJ IDEA
 * 项目: auth-server
 * 日期: 2024/9/18 23:46:44
 * 作者: qscy
 * 功能:
 **/
@Slf4j
@Setter
@Getter
public class SmsAuthenticationProvider implements AuthenticationProvider {

    private PasswordEncoder passwordEncoder;
    private AuthUserDetailsService userDetailsService;
    private RedisUtils redisUtils;


    public SmsAuthenticationProvider() {
        this(PasswordEncoderFactories.createDelegatingPasswordEncoder());
    }

    public SmsAuthenticationProvider(PasswordEncoder passwordEncoder) {
        this.setPasswordEncoder(passwordEncoder);
    }

    public void checkLoginInfo(String phone, String code) throws AuthenticationException {

        if (StringUtils.isBlank(phone)) {
            throw new BadCredentialsException("手机号错误");
        }
        if (StringUtils.isBlank(code)) {
            throw new BadCredentialsException("验证码错误");
        }


        if(!"999999".equals(code)) {
            if (!code.equals(redisUtils.getSmsCodeKey(phone))) {
                throw new BadCredentialsException("验证码错误");
            }
        }


    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        Assert.isInstanceOf(SmsAuthenticationToken.class, authentication, () -> {
            return "该请求不支持";
        });
        if (authentication.getPrincipal() == null && authentication.getCredentials() == null) {
            throw new BadCredentialsException("手机号或者验证码错误");
        }
        String phone = authentication.getPrincipal().toString();
        String code = authentication.getCredentials().toString();

        checkLoginInfo(phone, code);
        log.info("检查通过");

        AuthUserDetails user = userDetailsService.loadUserByUsername(phone);
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        SmsAuthenticationToken token = new SmsAuthenticationToken(phone, code, user.getAuthorities());
        token.setUid(user.getUid());
        user.setCode(code);
        token.setCode(user.getUsername());
        token.setUsername(user.getUsername());
        token.setPassword(user.getPassword());
        token.setDetails(user);
        log.info("验证成功");
        return token;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return SmsAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
